<!--
 * @Author: liu
 * @Date: 2024-05-22 00:57:18
 * @LastEditors: liu
 * @LastEditTime: 2024-07-09 23:11:37
 * @FilePath: \yyx_admin\src\views\courses\components\UploadVideoImgDialog.vue
 * @Description: 
 * 天道酬勤
-->
<template>
  <el-dialog
    v-model="dialogFormVisible"
    :title="title"
    width="500"
    :close-on-click-modal="false"
    :close-on-press-escape="false"
  >
    <div class="upload-body">
      <el-upload
        class="upload-box"
        action="#"
        accept="video/*"
        :show-file-list="false"
        :before-upload="handleBeforeVideoUpload"
        :disabled="vod.uploadDisabled"
      >
        <el-button type="primary" plain :disabled="vod.uploadDisabled"
          >选择视频</el-button
        >
        <template #tip>
          <div class="el-upload__tip">{{ vod.uploadVideoTip }}</div>
          <div style="margin-top: 15px; font-weight: 800">
            视频文件状态:
            <span style="color: #7a7c80">{{ vod.statusText }}</span>
          </div>
        </template>
      </el-upload>
      <el-upload
        class="upload-box"
        action="#"
        accept="image/*"
        :show-file-list="false"
        :http-request="handleUploadImage"
        :disabled="vod.coverBtnDisabled"
      >
        <el-button type="primary" plain :disabled="vod.coverBtnDisabled"
          >选择封面</el-button
        >
        <el-dialog
          v-model="innerVisible"
          width="400"
          height="100"
          title="提示"
          append-to-body
        >
          <span>点击开始上传后会覆盖原有视频！</span>
          <template #footer>
            <div class="dialog-footer">
              <el-button type="warning" @click="innerVisible = false">
                确定
              </el-button>
            </div>
          </template>
        </el-dialog>
        <template #tip>
          <div class="el-upload__tip">{{ vod.uploadCoverTip }}</div>
          <div style="margin-top: 15px; font-weight: 800">
            封面上传状态:
            <span style="color: #7a7c80">{{ vod.statusImgText }}</span>
          </div>
        </template>
      </el-upload>
      <el-button
        type="primary"
        @click="handleVideoUpload"
        :disabled="vod.uploadDisabled"
        >开始上传</el-button
      >

      <el-progress
        v-if="vod.uploadBox"
        :text-inside="true"
        :stroke-width="20"
        :percentage="vod.authProgress"
        style="margin-top: 15px"
        :format="uploadFormat"
        striped
        :color="colors"
      />
      <el-progress
        v-if="vod.transBox"
        :text-inside="true"
        :stroke-width="20"
        :percentage="vod.transPercent"
        style="margin-top: 15px"
        :format="transFormat"
        striped
        :color="colors"
      />
      <!-- <h4>视频转码进度：{{ vod.transPercent }}</h4> -->
    </div>

    <template #footer>
      <div class="dialog-footer">
        <el-button style="color: #606266" @click="dialogFormVisible = false"
          >取消</el-button
        >
        <el-button
          type="primary"
          :disabled="vod.submitDisabled"
          @click="onSubmit"
        >
          提交
        </el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { ref, reactive } from 'vue'
import { vodData, vodForm } from '@/api/upload/type'
import {
  ElMessage,
  UploadRequestHandler,
  UploadRequestOptions
} from 'element-plus'
//import axios from 'axios'
import {
  reqUploadImgAuth,
  reqUploadAuth,
  transCode,
  getTranscodeTask,
  updateLesson
} from '@/api/upload/ali'
import { layer } from '@layui/layer-vue'

const title = ref('')

const dialogFormVisible = ref(false)

//let isEdit = false
const innerVisible = ref(false)

//初始化视频上传对象
const initData = () => ({
  timeout: '',
  partSize: 0,
  parallel: '',
  retryCount: '',
  retryDuration: '',
  region: 'cn-shanghai',
  userId: '1303984639806000',
  //上传文件提示文字
  uploadVideoTip: '只支持MP4格式',
  //上传封面提示文字
  uploadCoverTip:
    '只支持jpg、png、gif格式（如未选择封面，会随机截取视频截图作为封面）',
  //file: null,
  uploader: null,
  //上传的视频文件
  videoFile: null,
  //上传视频文件id
  videoFileId: '',
  //视频原始文件名称
  videoName: '',
  //视频文件大小（字节）
  size: 0,
  //视频上传进度,
  authProgress: 0,
  //视频转码进度
  transPercent: 0,
  //上传文件盒子
  uploadBox: false,
  //转码盒子
  transBox: false,
  //视频状态
  vodStatus: 0,
  //视频状态文字
  statusText: '文件未选择。。',
  //封面状态文字
  statusImgText: '未选择封面。。',
  //封面状态
  coverStatus: 0,
  //封面原始文件名称
  coverName: '',
  //封面地址
  coverUrl: '',
  //封面选择按钮
  coverBtnDisabled: false,
  //上传视频按钮
  uploadDisabled: false,
  resumeDisabled: true,
  pauseDisabled: true,
  //提交按钮
  submitDisabled: true
})

//声明表单数据
const vod: vodData = reactive(initData())

//声明事件消息
const emits = defineEmits<{
  (e: 'vodChange'): void
}>()

//课程id
const id = ref(0)

//对话框初始化
const showAndInit = (_node: any, _data: any) => {
  console.log(_node, _data)
  dialogFormVisible.value = true
  //每次显示对话框，都先恢复为默认空值
  Object.assign(vod, initData())

  if (_data.vodStatus === 3) {
    //isEdit = true
    vod.uploadVideoTip = _data.videoName
    vod.statusText = '视频转码成功！！！'
    title.value = '编辑视频'
    vod.uploadCoverTip = _data.coverName
    vod.statusImgText = '封面已上传！！！'
    vod.coverStatus = _data.coverStatus
    vod.coverUrl = _data.coverUrl
    vod.coverName = _data.coverName
  } else {
    title.value = '上传视频'
  }

  //  console.log(_data.id, '...')
  id.value = _data.id

  //console.log(vod.vodStatus, 'vod.status')
}

/**==== 阿里云上传相关代码=== */

//创建上传实例
const createUploader = () => {
  return new AliyunUpload.Vod({
    timeout: vod.timeout || 60000,
    partSize: Math.round(vod.partSize || 1048576),
    parallel: vod.parallel || 5,
    retryCount: vod.retryCount || 3,
    retryDuration: vod.retryDuration || 2,
    region: vod.region,
    userId: vod.userId,
    localCheckpoint: true,
    //此参数是禁用服务端缓存，不影响断点续传
    // // 添加文件成功
    addFileSuccess: function (uploadInfo: any) {
      console.log(uploadInfo.videoId, 'uploadInfo.videoIdadd')
      console.log('addFileSuccess: ' + uploadInfo.file.name)
      vod.uploadDisabled = true
      vod.statusImgText = '封面已选择，等待上传。。'
    }
    // onUploadstarted: async function (uploadInfo: any) {}
  })
}

/* 1.封面上传开始==== */
const handleUploadImage: UploadRequestHandler = (
  option: UploadRequestOptions
): any => {
  vod.uploadCoverTip = option.file.name
  if (vod.uploader) {
    console.log('uploader实例已存在！')
    vod.uploader.stopUpload()
    vod.uploader = null
  }

  //1.创建上传实例
  vod.uploader = createUploader()

  //2.添加要上传的文件
  vod.uploader.addFile(option.file)

  //3.获取并配置上传凭证
  vod.uploader.options.onUploadstarted = async (uploadInfo: any) => {
    const res: any = await reqUploadImgAuth('default')
    console.log(res, 'res')
    const { coverId, imageURL, uploadAddress, uploadAuth } = res?.data
    vod.coverUrl = imageURL
    console.log(vod.coverUrl)
    try {
      vod.uploader.setUploadAuthAndAddress(
        uploadInfo,
        uploadAuth,
        uploadAddress,
        coverId
      )
    } catch (err: any) {
      throw new Error(err)
    }
  }

  //4.图片上传成功后执行的回调
  vod.uploader.options.onUploadSucceed = (uploadInfo: any) => {
    vod.uploadDisabled = false
    vod.statusImgText = '封面上传成功！！！'
    vod.coverStatus = 1
    vod.coverName = uploadInfo.file.name
    ElMessage.success('封面上传成功！！！')
  }

  //封面上传失败
  vod.uploader.options.onUploadFailed = () => {
    vod.uploadDisabled = false
    vod.statusImgText = '封面上传失败!'
    ElMessage.error('封面上传失败！！！')
    return
  }

  vod.uploader.startUpload()
}

/*封面上传结束==== */

/* 2.视频上传 */
//定义进度颜色变化
const colors = [
  { color: '#f56c6c', percentage: 20 },
  { color: '#e6a23c', percentage: 40 },
  { color: '#43B4FF', percentage: 60 },
  { color: '#5CB87A', percentage: 80 },
  { color: '#458A5C', percentage: 100 }
]
//上传进度条文字
const uploadFormat = (percentage: number) =>
  percentage === 100 ? '视频上传完毕' : `上传${percentage}%,请勿关闭窗口。。。`
//转码进度条文字
const transFormat = (percentage: number) =>
  percentage === 100 ? '视频转码完毕' : `视频转码中，请勿关闭窗口。。。`

//选择视频，并临时保存要上传的文件
const handleBeforeVideoUpload = (file: any) => {
  vod.videoFile = file
  // console.log('videFile', file)
  vod.uploadVideoTip = file.name
  vod.statusText = '添加视频文件成功, 等待上传...'
  if (vod.vodStatus == 3) {
    innerVisible.value = true
  }

  vod.uploadDisabled = false
  vod.uploader.stopUpload()
  return false
}

//开始上传
const handleVideoUpload = () => {
  // innerVisible.value = true
  // isEdit = true
  // console.log(vod.uploader)
  if (!vod.videoFile) {
    // ElMessage.error('请先选择需要上传的文件!')
    layer.msg('请先选择需要上传的视频文件!', { icon: 5, time: 2000 })
    //为了增强体验感，这里就不抛出错误了，直接return
    return
  }
  //上传开始后图片选择和文件选择按钮禁用
  vod.coverBtnDisabled = true
  vod.uploadDisabled = true

  if (vod.uploader) {
    console.log('uploader实例已存在', vod.uploader)
    vod.uploader = null
  }
  //1.获取上传实例
  vod.uploader = createUploader()

  //2.添加要上传的视频文件
  vod.uploader.addFile(vod.videoFile)

  //视频添加成功后执行的回调
  vod.uploader.options.addFileSuccess = async (uploadInfo: any) => {
    console.log(uploadInfo, 'uploadinfo')
    vod.statusText = '添加文件成功, 等待上传...'
    console.log('视频添加成功后执行的回调')
  }

  //3.获取并配置上传凭证
  vod.uploader.options.onUploadstarted = async (uploadInfo: any) => {
    const res: any = await reqUploadAuth(vod.videoFile.name, vod.coverUrl)

    const { uploadAddress, uploadAuth, videoId } = res?.data!

    vod.uploader.setUploadAuthAndAddress(
      uploadInfo,
      uploadAuth,
      uploadAddress,
      videoId
    )
    vod.videoFileId = videoId
    // console.log(res)
  }

  //4.视频上传成功后执行的回调
  vod.uploader.options.onUploadSucceed = (uploadInfo: any) => {
    console.log(uploadInfo, 'upoladInfo')
    vod.vodStatus = 1
    vod.videoName = uploadInfo.file.name
    vod.size = uploadInfo.file.size

    console.log(uploadInfo.file.name, vod.videoName, uploadInfo.file.size)

    ElMessage.success('视频上传成功！！！')
    vod.statusText = '视频文件上传成功！！！'
  }

  vod.uploader.options.onUploadFailed = async (
    uploadInfo: any,
    code: number,
    message: string
  ) => {
    console.log(
      'onUploadFailed: file:' +
        uploadInfo.file.name +
        ',code:' +
        code +
        ', message:' +
        message
    )
    vod.statusText = '文件上传失败!'
  }

  //6.视频转码处理
  vod.uploader.options.onUploadEnd = async () => {
    const res: any = await transCode({
      videoId: vod.videoFileId,
      templateGroupId: '421d2c3c19fbcc5eadc0ccfbcde99648'
    })

    //  console.log(res)
    if (res.code === 0) {
      vod.statusText = '视频转码中。。。'
      vod.vodStatus = 2
      //  console.log(res.data.transcodeTaskId)
      //每1秒获取转码进度值，当进度为100%时结束
      const timer = setInterval(async () => {
        const _res: any = await getTranscodeTask(res.data.transcodeTaskId)
        const data = _res.data.transcodeTask
        console.log(data)
        console.log(
          data.transcodeJobInfoList[0].transcodeProgress,
          data.taskStatus
        )

        if (_res.code === 0) {
          vod.transBox = true
          vod.transPercent = data.transcodeJobInfoList[0].transcodeProgress
        } else {
          ElMessage('视频转码异常！')
          vod.statusText = '视频转码异常！'
          vod.vodStatus = 4
          clearInterval(timer)
          throw new Error('视频转码异常！')
        }

        if (
          data.transcodeJobInfoList[0].TranscodeJobStatus === 'TranscodeFail'
        ) {
          vod.vodStatus = 4
          ElMessage('视频转码失败！')
          vod.statusText = '视频转码失败！'
          clearInterval(timer)
          throw new Error('视频转码失败！')
        }

        if (data.transcodeJobInfoList[0].transcodeProgress === 100) {
          console.log(data.taskStatus)
          clearInterval(timer)
          vod.statusText = '视频转码成功！！！'
          vod.vodStatus = 3
          ElMessage.success('视频转码成功！！！')
          vod.submitDisabled = false
        }
      }, 3000)
    }
  }
  //4.开始上传
  vod.uploader.startUpload()

  //文件上传进度
  vod.uploader.options.onUploadProgress = (
    _uploadInfo: any,
    _totalSize: number,
    percent: number
  ) => {
    vod.uploadBox = true
    vod.authProgress = Math.round(percent * 100)
    //console.log(vod.authProgress)
    vod.statusText = '文件上传中...'
  }
}

//整合需要提交的数据
const videoData: vodForm = reactive({
  id: 0,
  vodStatus: 0,
  videoName: '',
  videoId: '',
  size: 0,
  coverStatus: 0,
  coverName: '',
  coverUrl: ''
})

console.log(videoData)

const onSubmit = async () => {
  videoData.vodStatus = vod.vodStatus
  videoData.videoId = vod.videoFileId
  videoData.size = vod.size
  videoData.id = id.value
  videoData.videoName = vod.videoName
  videoData.coverStatus = vod.coverStatus
  videoData.coverName = vod.coverName
  videoData.coverStatus = vod.coverStatus
  videoData.coverUrl = vod.coverUrl

  const res = await updateLesson(videoData)

  if (res.code === 0) {
    ElMessage.success('课程信息已更新成功！！！')
    vod.submitDisabled = true

    emits('vodChange')
    // 设置三秒后执行的函数
    setTimeout(function () {
      dialogFormVisible.value = false
    }, 2000)
    //dialogFormVisible.value = false
  } else {
    ElMessage('课程信息更新失败！')
    // dialogFormVisible.value = false
    throw new Error('课程信息更新失败！')
  }

  console.log(res)
}

defineExpose({
  showAndInit
})
</script>

<style lang="scss" scoped>
.el-dialog {
  .upload-box {
    height: 110px;
  }
}

h4 {
  margin: 20px 0;
}
.upload-body {
  padding-left: 30px;
}
</style>
